package com.easymin.weixin.controller.v5;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.easymin.weixin.common.WxUtils;
import com.easymin.weixin.common.api.ZhuanXianApi;
import com.easymin.weixin.controller.v5.utils.ErrorMapV5;
import com.easymin.weixin.controller.v5.utils.ResultV5;
import com.easymin.weixin.entity.WxAccount;
import com.easymin.weixin.entity.WxApplication;
import com.easymin.weixin.manager.WxAccountManager;
import com.easymin.weixin.manager.WxApplicationManager;
import com.google.common.base.Preconditions;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.text.ParseException;
import java.util.*;

@Controller
@RequestMapping("v5/zhuanxian/")
public class ZhuanXianController {

	private static final String WX_ACCESS_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appid}&secret={secret}";

	private static final String WX_JSAPI_TICKET = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={access_token}&type=jsapi";

	@Autowired
	private WxApplicationManager wxApplicationManager;
	
	@Autowired
	private WxAccountManager wxAccountManager;

	@Autowired
	private RestTemplate restTemplate;

	@Autowired
	private ZhuanXianApi zhuanXianApi;


	/**
	 * 查询所有的线路的起点信息
	 * @param appKey 系统Key
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value="findStartCitys", method={RequestMethod.GET})
	public ResultV5 findLineAll(
			@RequestParam(required = true, value = "appKey") String appKey) {

		// 获取应用信息
		WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
		String server = wxApplication.getAddress();

		// 获取线路信息
		JSONObject data = zhuanXianApi.findLinesByParamsV5(null, appKey, server, null, null);

		// 获取专线线路失败
		if (null == data) {
			return ErrorMapV5.ERR_GET_CITY_LINE;
		}

		JSONObject data_ = data.getJSONObject("data");
		
		// 获取出所有的起点城市
		List<Map<String, Object>> startCitys = new ArrayList<Map<String, Object>>();
		JSONArray lines = data_.getJSONArray("rows");
		
		List<String> cityList = new ArrayList<String>();
		List<String> cityRecordList = new ArrayList<String>();

		if (null != lines && lines.size() > 0) {
			for (Object obj : lines) {
				String startCity = ((JSONObject) obj).getString("startCity");
				if (!cityList.contains(startCity)) {
					cityList.add(startCity);
				}
				String endCity = ((JSONObject) obj).getString("endCity");
				if (!cityList.contains(endCity)) {
					cityList.add(endCity);
				}
			}
			
			for (String city : cityList) {
				
				// 临时存储一些数据
				Map<String, Object> dataMap = new LinkedHashMap<String, Object>();
				List<String> address = new ArrayList<String>();
				
				// 已经获取过的起点城市不再获取
				if (cityRecordList.contains(city)) {
					continue;
				}

				// 获取该起点城市的起点地址
				for (Object obj : lines) {
					String startCity = ((JSONObject) obj).getString("startCity"); // 起点城市
					if (city.equals(startCity)) { // 城市名匹配了，获取起点地址
						String startAddress = ((JSONObject) obj).getString("startAddress"); // 起点地址
						if (!address.contains(startAddress)) {
							address.add(startAddress);
							if (!cityRecordList.contains(startCity)) { // 将该次的城市记录下来，下次就不再去获取该城市的起点地址了
								cityRecordList.add(startCity);
							}
						}
					}
					
					String endCity = ((JSONObject) obj).getString("endCity"); // 起点城市
					if (city.equals(endCity)) { // 城市名匹配了，获取起点地址
						String endAddress = ((JSONObject) obj).getString("endAddress"); // 起点地址
						if (!address.contains(endAddress)) {
							address.add(endAddress);
							if (!cityRecordList.contains(endCity)) { // 将该次的城市记录下来，下次就不再去获取该城市的起点地址了
								cityRecordList.add(endCity);
							}
						}
					}
				}

				// 加入数据
				dataMap.put("city", city);
				dataMap.put("address", address);
				startCitys.add(dataMap);
			}
		}

		ResultV5 result = ErrorMapV5.ERR_SUCCESS.clone();
		result.setData(startCitys);
		return result;
	}

	/**
	 * 根据起点信息获取该起点所有对应线路的终点信息
	 * @param appKey 系统Key
	 * @param startCity 起点城市
	 * @param startAddress 起点地址
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value="findEndCitysByStartInfo", method={RequestMethod.GET})
	public ResultV5 findEndCitysByStartInfo (
			@RequestParam(required = true, value = "appKey") String appKey,
			@RequestParam(required = true, value = "startCity") String startCity,
			@RequestParam(required = true, value = "startAddress") String startAddress) {

		// 获取应用信息
		WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
		String server = wxApplication.getAddress();

		// 获取线路信息
		JSONObject data = zhuanXianApi.findLinesByParamsV5(null, appKey, server, null, null);

		// 获取专线线路失败
		if (null == data) {
			return ErrorMapV5.ERR_GET_CITY_LINE;
		}

		// 所有的线路信息
		JSONObject data_ = data.getJSONObject("data");
		
		// 存储终点信息
		List<Map<String, Object>> endCitys = new ArrayList<Map<String, Object>>();

		// 获取出所有线路信息
		JSONArray lines = data_.getJSONArray("rows");

		if (null != lines && lines.size() > 0) {
			for (Object obj : lines) {

				// 临时存储数据
				Map<String, Object> dataMap = new LinkedHashMap<String, Object>();
				List<Map<String, Object>> address = new ArrayList<Map<String, Object>>();

				// 遍历线路起点城市、起点地址
				String sCity = ((JSONObject) obj).getString("startCity");
				String sAddress = ((JSONObject) obj).getString("startAddress");

				// 信息匹配了，获取终点信息
				if (startCity.equals(sCity) && startAddress.equals(sAddress)) {

					// 终点城市
					String eCity = ((JSONObject) obj).getString("endCity");

					// 取该终点城市的所有终点地址
					for (Object obj2 : lines) {

						// 临时存储地址信息
						Map<String, Object> addressMap = new LinkedHashMap<String, Object>();

						// 终点城市
						String eCity2 = ((JSONObject) obj2).getString("endCity");

						// 终点城市匹配了，获取该终点城市的所有地址
						if (eCity.equals(eCity2)) {

							// 终点地址
							String eAddress2 = ((JSONObject) obj2).getString("endAddress");
							String sCity2 = ((JSONObject) obj2).getString("startCity");
							String sAddress2 = ((JSONObject) obj2).getString("startAddress");

							// 判断该终点地址是否已经存在了，存在就不管了，不存在就添加
							boolean isContains = false;
							if (null != address && !address.isEmpty()) {
								for (Map<String, Object> map : address) {
									String eAddress_ = String.valueOf(map.get("endAddress"));
									if (eAddress_.contains(eAddress2)) {
										isContains = true;
									}
								}
							}

							// 不存在，添加
							if (!isContains && sAddress2.equals(sAddress) && sCity2.equals(startCity)) {
								addressMap.put("endCity", eCity2);
								addressMap.put("endAddress", eAddress2);
								addressMap.put("lineId", ((JSONObject) obj2).getString("lineId"));
								addressMap.put("companyId", ((JSONObject) obj2).getString("companyId"));
								addressMap.put("companyName", ((JSONObject) obj2).getString("companyName"));
								addressMap.put("jihuoMoney", ((JSONObject) obj2).getString("jihuoMoney"));
								addressMap.put("baocheMoney", ((JSONObject) obj2).getString("baocheMoney"));
								addressMap.put("pincheMoney", ((JSONObject) obj2).getString("pincheMoney"));
								addressMap.put("pincheAreaId", ((JSONObject) obj2).getString("pincheAreaId"));
								addressMap.put("baocheAreaId", ((JSONObject) obj2).getString("baocheAreaId"));
								addressMap.put("jihuoAreaId", ((JSONObject) obj2).getString("jihuoAreaId"));
								addressMap.put("lineName", ((JSONObject) obj2).getString("name"));
								addressMap.put("startCity", ((JSONObject) obj2).getString("startCity"));
								addressMap.put("startAddress", ((JSONObject) obj2).getString("startAddress"));
								addressMap.put("peopleNumber", ((JSONObject) obj2).getString("peopleNumber"));
								addressMap.put("numberOfVehicles",((JSONObject) obj2).getString("numberOfVehicles"));
								addressMap.put("contactNubmer",((JSONObject)obj2).getString("contactNumber"));
								address.add(addressMap);
							}
						}
					}

					// 加入数据
					dataMap.put("city", eCity);
					dataMap.put("address", address);
					boolean isExsit = false;
					//判断是否已经存在该城市，如果已经存在就不添加
					for(Map<String, Object> map : endCitys){
						String endCity = map.get("city").toString();
						//如果存在
						if(endCity.equals(eCity)) {
							isExsit = true;
							break;
						}
					}
					if(!isExsit)
						endCitys.add(dataMap);
				}
			}
		}

		ResultV5 result = ErrorMapV5.ERR_SUCCESS.clone();
		result.setData(endCitys);
		return result;
	}
	
	/**
	 * 
	 * @param appKey
	 * @param startCity
	 * @param startAddress
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value="findEndByStart", method={RequestMethod.GET})
	public ResultV5 findEndByStart (
			@RequestParam(required = true, value = "appKey") String appKey,
			@RequestParam(required = true, value = "startCity") String startCity,
			@RequestParam(required = true, value = "startAddress") String startAddress) {

		try {
			// 获取应用信息
			WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
			String server = wxApplication.getAddress();

			// 获取线路信息
			JSONObject data = zhuanXianApi.findEndByStart(startCity, startAddress, appKey, server, null, null);

			// 获取专线线路失败
			if (null == data) {
				return ErrorMapV5.ERR_GET_CITY_LINE;
			}

			// 所有的线路信息
			JSONObject data_ = data.getJSONObject("data");
			
			// 存储终点信息
			List<String> citys =  new ArrayList<String>();
			List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();

			// 获取出所有线路信息
			JSONArray lines = data_.getJSONArray("rows");
			if (null != lines && lines.size() > 0) {
				for (Object obj : lines) {
					String sCity = ((JSONObject) obj).getString("startCity");
					String sAddress = ((JSONObject) obj).getString("startAddress");
					String endCity = ((JSONObject) obj).getString("endCity");
					String endAddress = ((JSONObject) obj).getString("endAddress");
					if (startCity.equals(sCity) && startAddress.equals(sAddress)){
						if (!citys.contains(endCity)) {
							citys.add(endCity);
						}
					} 
					if (startCity.equals(endCity) && startAddress.equals(endAddress)) {
						if (!citys.contains(sCity)) {
							citys.add(sCity);
						}
					}
				}
				
				for (String ends : citys) {
					
					List<Map<String, Object>> address = new ArrayList<Map<String, Object>>();
					Map<String, Object> dataMap = new HashMap<String, Object>();
					
					for (Object obj : lines) {
						List<String> addrs =  new ArrayList<String>();
						Map<String, Object> saddressMap = new HashMap<String, Object>();
						Map<String, Object> eaddressMap = new HashMap<String, Object>();
						String sCity = ((JSONObject) obj).getString("startCity");
						if (sCity.equals(ends)) {
							String saddr = ((JSONObject) obj).getString("startAddress");
							if (!addrs.contains(saddr)) {
								addrs.add(saddr);
								saddressMap.put("lineId", ((JSONObject) obj).getString("lineId"));
								saddressMap.put("companyId", ((JSONObject) obj).getString("companyId"));
								saddressMap.put("companyName", ((JSONObject) obj).getString("companyName"));
								saddressMap.put("jihuoMoney", ((JSONObject) obj).getString("jihuoMoney"));
								saddressMap.put("baocheMoney", ((JSONObject) obj).getString("baocheMoney"));
								saddressMap.put("pincheMoney", ((JSONObject) obj).getString("pincheMoney"));
								saddressMap.put("pincheAreaId", ((JSONObject) obj).getString("pincheAreaId"));
								saddressMap.put("baocheAreaId", ((JSONObject) obj).getString("baocheAreaId"));
								saddressMap.put("jihuoAreaId", ((JSONObject) obj).getString("jihuoAreaId"));
								saddressMap.put("lineName", ((JSONObject) obj).getString("name"));
								saddressMap.put("startCity", ((JSONObject) obj).getString("startCity"));
								saddressMap.put("startAddress", ((JSONObject) obj).getString("startAddress"));
								address.add(saddressMap);
							}
						}
						String eCity = ((JSONObject) obj).getString("endCity");
						if (eCity.equals(ends)) {
							String eaddr = ((JSONObject) obj).getString("endAddress");
							if (!addrs.contains(eaddr)) {
								addrs.add(eaddr);
								eaddressMap.put("lineId", ((JSONObject) obj).getString("lineId"));
								eaddressMap.put("companyId", ((JSONObject) obj).getString("companyId"));
								eaddressMap.put("companyName", ((JSONObject) obj).getString("companyName"));
								eaddressMap.put("jihuoMoney", ((JSONObject) obj).getString("jihuoMoney"));
								eaddressMap.put("baocheMoney", ((JSONObject) obj).getString("baocheMoney"));
								eaddressMap.put("pincheMoney", ((JSONObject) obj).getString("pincheMoney"));
								eaddressMap.put("pincheAreaId", ((JSONObject) obj).getString("pincheAreaId"));
								eaddressMap.put("baocheAreaId", ((JSONObject) obj).getString("baocheAreaId"));
								eaddressMap.put("jihuoAreaId", ((JSONObject) obj).getString("jihuoAreaId"));
								eaddressMap.put("lineName", ((JSONObject) obj).getString("name"));
								eaddressMap.put("endCity", ((JSONObject) obj).getString("endCity"));
								eaddressMap.put("endAddress", ((JSONObject) obj).getString("endAddress"));
								address.add(eaddressMap);
							}
						}
					}
					dataMap.put("city", ends);
					dataMap.put("address", address);
					list.add(dataMap);
				}
			}

			ResultV5 result = ErrorMapV5.ERR_SUCCESS.clone();
			result.setData(list);
			return result;
		} catch (Exception e) {
			e.printStackTrace();
			return ErrorMapV5.ERR_SYSTEM;
		}
	}

	/**
	   * 下单v5.
	   * @param appKey 系统key
	   * @param orderType 订单类型
	   * @param passengerId 客户id  false
	   * @param passengerPhone 客户手机号
	   * @param lineId 路线id
	   * @param startAddress 开始地址
	   * @param startLat 开始纬度
	   * @param startLng 开始经度
	   * @param endAddress 结束地址 false
	   * @param endLat 结束纬度 false
	   * @param ack 区分公司 false
	   * @param lat 纬度 false
	   * @param lng 经度 false
	   * @param endLng 结束经度 false
	   * @param startTime 开始时间
	   * @param budgetPay 预算价格 false
	   * @param memo 备注 false
	   * @param couponId 优惠券id false
	   * @param peopleNumber 人数 false
	   * @param takeDeliveryName 收货人名称 false
	   * @param takeDeliveryPhone 收货人电话 false
	   * @param openId 微信id false
	   * @return JSONObject
	   */
	@ResponseBody
	@RequestMapping(value = "makeAnZXAppointmentV5", method = RequestMethod.POST)
	public JSONObject makeAnZhuanxianAppointmentV4(
	    @RequestParam(required = true, value = "appkey") String appKey,
	    @RequestParam(required = true, value = "orderType") String orderType,
	    @RequestParam(required = true, value = "passengerPhone") String passengerPhone,
	    @RequestParam(required = true, value = "lineId") Long lineId,
	    @RequestParam(required = true, value = "startAddress") String startAddress, 
	    @RequestParam(required = true, value = "startLat") Double startLat,
	    @RequestParam(required = true, value = "startLng") Double startLng,
	    @RequestParam(required = true, value = "startTime") Long startTime, 
	    @RequestParam(required = true, value = "endAddress") String endAddress,
	    @RequestParam(required = true, value = "endLat") Double endLat, 
	    @RequestParam(required = true, value = "endLng") Double endLng,
	    @RequestParam(required = false, value = "ack") String ack,
	    @RequestParam(required = false, value = "lat") Double lat, 
	    @RequestParam(required = false, value = "lng") Double lng,
	    @RequestParam(required = false, value = "passengerId") Long passengerId,
	    @RequestParam(required = false, value = "budgetPay") Double budgetPay,
	    @RequestParam(required = false, value = "memo") String memo, 
	    @RequestParam(required = false, value = "couponId") Long couponId,
	    @RequestParam(required = false, value = "peopleNumber") Long peopleNumber,
	    @RequestParam(required = false, value = "takeDeliveryName") String takeDeliveryName, 
	    @RequestParam(required = false, value = "takeDeliveryPhone") String takeDeliveryPhone,
	    @RequestParam(required = false, value = "openId") String openId) throws ParseException {

	    WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
	    Preconditions.checkArgument(null != wxApplication, "appKey错误");

	    return zhuanXianApi.makeAnZhuanxianAppointmentV4(wxApplication.getAddress(), appKey, orderType,
	        passengerId, passengerPhone, lineId, startAddress, startLat, startLng, endAddress, endLat,
	        endLng, startTime, budgetPay, couponId, peopleNumber, memo, takeDeliveryName,
	        takeDeliveryPhone, ack, lat, lng, openId);
	  }

	/**
	 * 查询订单信息
	 * @param appKey 系统key
	 * @param orderId 订单id
	 * @return JSONObject
	 */
	@ResponseBody
	@RequestMapping(value = "findZXOrder", method = {RequestMethod.GET})
	public ResultV5 findZhuanxianOrder(
			@RequestParam(required=true, value="appKey") String appKey, 
			@RequestParam(required=true, value="orderId") Long orderId) throws Exception {

		JSONObject json = zhuanXianApi.getOrderByIdV5(appKey, orderId);
		if (null == json) {
			return ErrorMapV5.ERR_GET_ZHUANXIAN_ORDER;
		}

		JSONObject data = json.getJSONObject("data");
		ResultV5 result = ErrorMapV5.ERR_SUCCESS.clone();
		result.setData(data);
		return result;
	}

	/**
	 * 获取订单评价
	 * @param appKey 系统key
	 * @param orderId 订单号
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "getReview", method = {RequestMethod.GET})
	public ResultV5 getReview (
			@RequestParam(required=true, value="appKey") String appKey, 
			@RequestParam(required=true, value="orderId") Long orderId) {
		
		JSONObject json = zhuanXianApi.getReviewV5(appKey, orderId);
		if (null == json) {
			return ErrorMapV5.ERR_GET_ZHUANXIAN_REVIEW;
		}
		JSONObject data = json.getJSONObject("data");
		ResultV5 result = ErrorMapV5.ERR_SUCCESS.clone();
		result.setData(data);
		return result;
	}
	
	/**
	 * 微信支付
	 * @param appKey 系统key
	 * @param orderId 订单id
	 * @param openId 微信id
	 * @param appId 微信应用id
	 * @param request 判断是否来自微信
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "doPayForWx", method = RequestMethod.POST)
	public ResultV5 doPayForWx(
			@RequestParam(required = true, value = "appKey") String appKey,
			@RequestParam(required = true, value = "orderId") Long orderId,
			@RequestParam(required = true, value = "openId") String openId,
			@RequestParam(required = true, value = "appId") String appId, 
			HttpServletRequest request) {

		ResultV5 result = null;
		try {
			WxApplication wxApplication = wxApplicationManager.findByAppKey(appKey);
			Preconditions.checkArgument(null != wxApplication, "appKey错误");

			WxAccount wxAccount = wxAccountManager.findBy(appId, wxApplication.getId());
			Preconditions.checkArgument(null != wxAccount, "appid错误");

			// 判断是否来自微信
			StringBuilder sb = new StringBuilder();
			sb.append(request.getScheme());
			sb.append("://");
			sb.append(request.getServerName());
			int port = request.getServerPort();
			if (port != 80) {
				sb.append(":").append(port);
			}
			sb.append(request.getRequestURI());
			String queryString = request.getQueryString();
			if (StringUtils.isNotBlank(queryString)) {
				sb.append("?");
				sb.append(queryString);
			}

			JSONObject jsonObject = new JSONObject();
			JSONObject jo = zhuanXianApi.getZxWxPrepayId(wxApplication.getAddress(), orderId, openId);
			jsonObject.put("package", jo.getString("package"));
			jsonObject.put("timestamp", jo.getString("timeStamp"));
			jsonObject.put("url", sb.toString());
			jsonObject.put("nonceStr", jo.getString("nonceStr"));
			jsonObject.put("paySign", jo.getString("paySign"));

			// 获取微信AccessToken
			String response = restTemplate.getForObject(WX_ACCESS_TOKEN, String.class, wxAccount.getWxappId(),
					wxAccount.getAppsecret());
			JSONObject ac = JSON.parseObject(response);

			if (ac.containsKey("access_token")) {
				String accessToken = ac.getString("access_token"); // 获取微信access_token
				// 获取jsapi_ticket
				String resp = restTemplate.getForObject(WX_JSAPI_TICKET, String.class, accessToken);
				JSONObject ticketJson = JSON.parseObject(resp);
				if (ticketJson.containsKey("ticket")) {
					String ticket = ticketJson.getString("ticket");
					jsonObject.put("jsapi_ticket", ticket);
					Map<String, Object> signParams = new HashMap<>();
					signParams.put("jsapi_ticket", ticket);
					signParams.put("timestamp", jo.getString("timestamp"));
					signParams.put("url", sb.toString());
					signParams.put("noncestr", jo.getString("noncestr"));
					jsonObject.put("signature", WxUtils.buildSha1Sign(signParams));

					result = ErrorMapV5.ERR_SUCCESS.clone();
					result.setData(jsonObject);
					return result;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			return ErrorMapV5.ERR_SYSTEM;
		}
		return ErrorMapV5.ERR_GET_WECHAT_PAY_PARAMS;
	}
}
